const { ExtensionState } = ExtensionUtils;
-// Arrays of uuids
-var enabledExtensions;
-// Contains the order that extensions were enabled in.
-var extensionOrder = [];
-
-// We don't really have a class to add signals on. So, create
-// a simple dummy object, add the signal methods, and export those
-// publically.
-var _signals = {};
-Signals.addSignalMethods(_signals);
-
-var connect = _signals.connect.bind(_signals);
-var disconnect = _signals.disconnect.bind(_signals);
-
const ENABLED_EXTENSIONS_KEY = 'enabled-extensions';
const DISABLE_USER_EXTENSIONS_KEY = 'disable-user-extensions';
const EXTENSION_DISABLE_VERSION_CHECK_KEY = 'disable-extension-version-validation';
-var initted = false;
-var enabled;
+var ExtensionManager = class {
+ constructor() {
+ this._initted = false;
+ this._enabled = false;
-function disableExtension(uuid) {
- let extension = ExtensionUtils.extensions[uuid];
- if (!extension)
- return;
+ this._enabledExtensions = [];
+ this._extensionOrder = [];
- if (extension.state != ExtensionState.ENABLED)
- return;
+ Main.sessionMode.connect('updated', this._sessionUpdated.bind(this));
+ this._sessionUpdated();
+ }
- // "Rebase" the extension order by disabling and then enabling extensions
- // in order to help prevent conflicts.
+ disableExtension(uuid) {
+ let extension = ExtensionUtils.extensions[uuid];
+ if (!extension)
+ return;
- // Example:
- // order = [A, B, C, D, E]
- // user disables C
- // this should: disable E, disable D, disable C, enable D, enable E
+ if (extension.state != ExtensionState.ENABLED)
+ return;
- let orderIdx = extensionOrder.indexOf(uuid);
- let order = extensionOrder.slice(orderIdx + 1);
- let orderReversed = order.slice().reverse();
+ // "Rebase" the extension order by disabling and then enabling extensions
+ // in order to help prevent conflicts.
+
+ // Example:
+ // order = [A, B, C, D, E]
+ // user disables C
+ // this should: disable E, disable D, disable C, enable D, enable E
+
+ let orderIdx = this._extensionOrder.indexOf(uuid);
+ let order = this._extensionOrder.slice(orderIdx + 1);
+ let orderReversed = order.slice().reverse();
+
+ for (let i = 0; i < orderReversed.length; i++) {
+ let uuid = orderReversed[i];
+ try {
+ ExtensionUtils.extensions[uuid].stateObj.disable();
+ } catch (e) {
+ this.logExtensionError(uuid, e);
+ }
+ }
+
+ if (extension.stylesheet) {
+ let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
+ theme.unload_stylesheet(extension.stylesheet);
+ delete extension.stylesheet;
+ }
- for (let i = 0; i < orderReversed.length; i++) {
- let uuid = orderReversed[i];
try {
- ExtensionUtils.extensions[uuid].stateObj.disable();
+ extension.stateObj.disable();
} catch (e) {
- logExtensionError(uuid, e);
+ this.logExtensionError(uuid, e);
}
- }
- if (extension.stylesheet) {
- let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
- theme.unload_stylesheet(extension.stylesheet);
- delete extension.stylesheet;
- }
+ for (let i = 0; i < order.length; i++) {
+ let uuid = order[i];
+ try {
+ ExtensionUtils.extensions[uuid].stateObj.enable();
+ } catch (e) {
+ this.logExtensionError(uuid, e);
+ }
+ }
- try {
- extension.stateObj.disable();
- } catch (e) {
- logExtensionError(uuid, e);
- }
+ this._extensionOrder.splice(orderIdx, 1);
- for (let i = 0; i < order.length; i++) {
- let uuid = order[i];
- try {
- ExtensionUtils.extensions[uuid].stateObj.enable();
- } catch (e) {
- logExtensionError(uuid, e);
+ if (extension.state != ExtensionState.ERROR) {
+ extension.state = ExtensionState.DISABLED;
+ this.emit('extension-state-changed', extension);
}
}
- extensionOrder.splice(orderIdx, 1);
-
- if ( extension.state != ExtensionState.ERROR ) {
- extension.state = ExtensionState.DISABLED;
- _signals.emit('extension-state-changed', extension);
- }
-}
+ enableExtension(uuid) {
+ let extension = ExtensionUtils.extensions[uuid];
+ if (!extension)
+ return;
-function enableExtension(uuid) {
- let extension = ExtensionUtils.extensions[uuid];
- if (!extension)
- return;
+ if (extension.state == ExtensionState.INITIALIZED)
+ this.initExtension(uuid);
- if (extension.state == ExtensionState.INITIALIZED)
- initExtension(uuid);
+ if (extension.state != ExtensionState.DISABLED)
+ return;
- if (extension.state != ExtensionState.DISABLED)
- return;
+ this._extensionOrder.push(uuid);
- extensionOrder.push(uuid);
+ let stylesheetNames = [`${global.session_mode}.css`, 'stylesheet.css'];
+ let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
+ for (let i = 0; i < stylesheetNames.length; i++) {
+ try {
+ let stylesheetFile = extension.dir.get_child(stylesheetNames[i]);
+ theme.load_stylesheet(stylesheetFile);
+ extension.stylesheet = stylesheetFile;
+ break;
+ } catch (e) {
+ if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
+ continue; // not an error
+ log(`Failed to load stylesheet for extension ${uuid}: ${e.message}`);
+ return;
+ }
+ }
- let stylesheetNames = [`${global.session_mode}.css`, 'stylesheet.css'];
- let theme = St.ThemeContext.get_for_stage(global.stage).get_theme();
- for (let i = 0; i < stylesheetNames.length; i++) {
try {
- let stylesheetFile = extension.dir.get_child(stylesheetNames[i]);
- theme.load_stylesheet(stylesheetFile);
- extension.stylesheet = stylesheetFile;
- break;
+ extension.stateObj.enable();
+ extension.state = ExtensionState.ENABLED;
+ this.emit('extension-state-changed', extension);
+ return;
} catch (e) {
- if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.NOT_FOUND))
- continue; // not an error
- log(`Failed to load stylesheet for extension ${uuid}: ${e.message}`);
+ if (extension.stylesheet) {
+ theme.unload_stylesheet(extension.stylesheet);
+ delete extension.stylesheet;
+ }
+ this.logExtensionError(uuid, e);
return;
}
}
- try {
- extension.stateObj.enable();
- extension.state = ExtensionState.ENABLED;
- _signals.emit('extension-state-changed', extension);
- return;
- } catch (e) {
- if (extension.stylesheet) {
- theme.unload_stylesheet(extension.stylesheet);
- delete extension.stylesheet;
- }
- logExtensionError(uuid, e);
- return;
- }
-}
-
-function logExtensionError(uuid, error) {
- let extension = ExtensionUtils.extensions[uuid];
- if (!extension)
- return;
+ logExtensionError(uuid, error) {
+ let extension = ExtensionUtils.extensions[uuid];
+ if (!extension)
+ return;
- let message = `${error}`;
+ let message = `${error}`;
- extension.state = ExtensionState.ERROR;
- if (!extension.errors)
- extension.errors = [];
- extension.errors.push(message);
+ extension.state = ExtensionState.ERROR;
+ if (!extension.errors)
+ extension.errors = [];
+ extension.errors.push(message);
- log('Extension "%s" had error: %s'.format(uuid, message));
- _signals.emit('extension-state-changed', { uuid: uuid,
+ log('Extension "%s" had error: %s'.format(uuid, message));
+ this.emit('extension-state-changed', { uuid: uuid,
error: message,
state: extension.state });
-}
+ }
-function loadExtension(extension) {
- // Default to error, we set success as the last step
- extension.state = ExtensionState.ERROR;
+ loadExtension(extension) {
+ // Default to error, we set success as the last step
+ extension.state = ExtensionState.ERROR;
- let checkVersion = !global.settings.get_boolean(EXTENSION_DISABLE_VERSION_CHECK_KEY);
+ let checkVersion = !global.settings.get_boolean(EXTENSION_DISABLE_VERSION_CHECK_KEY);
- if (checkVersion && ExtensionUtils.isOutOfDate(extension)) {
- extension.state = ExtensionState.OUT_OF_DATE;
- } else {
- let enabled = enabledExtensions.includes(extension.uuid);
- if (enabled) {
- if (!initExtension(extension.uuid))
- return;
- if (extension.state == ExtensionState.DISABLED)
- enableExtension(extension.uuid);
+ if (checkVersion && ExtensionUtils.isOutOfDate(extension)) {
+ extension.state = ExtensionState.OUT_OF_DATE;
} else {
- extension.state = ExtensionState.INITIALIZED;
+ let enabled = this._enabledExtensions.includes(extension.uuid);
+ if (enabled) {
+ if (!this.initExtension(extension.uuid))
+ return;
+ if (extension.state == ExtensionState.DISABLED)
+ this.enableExtension(extension.uuid);
+ } else {
+ extension.state = ExtensionState.INITIALIZED;
+ }
}
+
+ this.emit('extension-state-changed', extension);
}
- _signals.emit('extension-state-changed', extension);
-}
-
-function unloadExtension(extension) {
- // Try to disable it -- if it's ERROR'd, we can't guarantee that,
- // but it will be removed on next reboot, and hopefully nothing
- // broke too much.
- disableExtension(extension.uuid);
-
- extension.state = ExtensionState.UNINSTALLED;
- _signals.emit('extension-state-changed', extension);
-
- delete ExtensionUtils.extensions[extension.uuid];
- return true;
-}
-
-function reloadExtension(oldExtension) {
- // Grab the things we'll need to pass to createExtensionObject
- // to reload it.
- let { uuid: uuid, dir: dir, type: type } = oldExtension;
-
- // Then unload the old extension.
- unloadExtension(oldExtension);
-
- // Now, recreate the extension and load it.
- let newExtension;
- try {
- newExtension = ExtensionUtils.createExtensionObject(uuid, dir, type);
- } catch (e) {
- logExtensionError(uuid, e);
- return;
+ unloadExtension(extension) {
+ // Try to disable it -- if it's ERROR'd, we can't guarantee that,
+ // but it will be removed on next reboot, and hopefully nothing
+ // broke too much.
+ this.disableExtension(extension.uuid);
+
+ extension.state = ExtensionState.UNINSTALLED;
+ this.emit('extension-state-changed', extension);
+
+ delete ExtensionUtils.extensions[extension.uuid];
+ return true;
}
- loadExtension(newExtension);
-}
+ reloadExtension(oldExtension) {
+ // Grab the things we'll need to pass to createExtensionObject
+ // to reload it.
+ let { uuid: uuid, dir: dir, type: type } = oldExtension;
-function initExtension(uuid) {
- let extension = ExtensionUtils.extensions[uuid];
- let dir = extension.dir;
+ // Then unload the old extension.
+ this.unloadExtension(oldExtension);
- if (!extension)
- throw new Error("Extension was not properly created. Call loadExtension first");
+ // Now, recreate the extension and load it.
+ let newExtension;
+ try {
+ newExtension = ExtensionUtils.createExtensionObject(uuid, dir, type);
+ } catch (e) {
+ this.logExtensionError(uuid, e);
+ return;
+ }
- let extensionJs = dir.get_child('extension.js');
- if (!extensionJs.query_exists(null)) {
- logExtensionError(uuid, new Error('Missing extension.js'));
- return false;
+ this.loadExtension(newExtension);
}
- let extensionModule;
- let extensionState = null;
+ initExtension(uuid) {
+ let extension = ExtensionUtils.extensions[uuid];
+ let dir = extension.dir;
- ExtensionUtils.installImporter(extension);
- try {
- extensionModule = extension.imports.extension;
- } catch (e) {
- logExtensionError(uuid, e);
- return false;
- }
+ if (!extension)
+ throw new Error("Extension was not properly created. Call loadExtension first");
+
+ let extensionJs = dir.get_child('extension.js');
+ if (!extensionJs.query_exists(null)) {
+ this.logExtensionError(uuid, new Error('Missing extension.js'));
+ return false;
+ }
+
+ let extensionModule;
+ let extensionState = null;
- if (extensionModule.init) {
+ ExtensionUtils.installImporter(extension);
try {
- extensionState = extensionModule.init(extension);
+ extensionModule = extension.imports.extension;
} catch (e) {
- logExtensionError(uuid, e);
+ this.logExtensionError(uuid, e);
return false;
}
+
+ if (extensionModule.init) {
+ try {
+ extensionState = extensionModule.init(extension);
+ } catch (e) {
+ this.logExtensionError(uuid, e);
+ return false;
+ }
+ }
+
+ if (!extensionState)
+ extensionState = extensionModule;
+ extension.stateObj = extensionState;
+
+ extension.state = ExtensionState.DISABLED;
+ this.emit('extension-loaded', uuid);
+ return true;
}
- if (!extensionState)
- extensionState = extensionModule;
- extension.stateObj = extensionState;
-
- extension.state = ExtensionState.DISABLED;
- _signals.emit('extension-loaded', uuid);
- return true;
-}
-
-function getEnabledExtensions() {
- let extensions;
- if (Array.isArray(Main.sessionMode.enabledExtensions))
- extensions = Main.sessionMode.enabledExtensions;
- else
- extensions = [];
-
- if (global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY))
- return extensions;
-
- return extensions.concat(global.settings.get_strv(ENABLED_EXTENSIONS_KEY));
-}
-
-function onEnabledExtensionsChanged() {
- let newEnabledExtensions = getEnabledExtensions();
-
- if (!enabled)
- return;
-
- // Find and enable all the newly enabled extensions: UUIDs found in the
- // new setting, but not in the old one.
- newEnabledExtensions.filter(
- uuid => !enabledExtensions.includes(uuid)
- ).forEach(uuid => {
- enableExtension(uuid);
- });
-
- // Find and disable all the newly disabled extensions: UUIDs found in the
- // old setting, but not in the new one.
- enabledExtensions.filter(
- item => !newEnabledExtensions.includes(item)
- ).forEach(uuid => {
- disableExtension(uuid);
- });
-
- enabledExtensions = newEnabledExtensions;
-}
-
-function _onVersionValidationChanged() {
- // we want to reload all extensions, but only enable
- // extensions when allowed by the sessionMode, so
- // temporarily disable them all
- enabledExtensions = [];
- for (let uuid in ExtensionUtils.extensions)
- reloadExtension(ExtensionUtils.extensions[uuid]);
- enabledExtensions = getEnabledExtensions();
-
- if (Main.sessionMode.allowExtensions) {
- enabledExtensions.forEach(uuid => {
- enableExtension(uuid);
- });
+ _getEnabledExtensions() {
+ let extensions;
+ if (Array.isArray(Main.sessionMode.enabledExtensions))
+ extensions = Main.sessionMode.enabledExtensions;
+ else
+ extensions = [];
+
+ if (global.settings.get_boolean(DISABLE_USER_EXTENSIONS_KEY))
+ return extensions;
+
+ return extensions.concat(global.settings.get_strv(ENABLED_EXTENSIONS_KEY));
}
-}
-
-function _loadExtensions() {
- global.settings.connect(`changed::${ENABLED_EXTENSIONS_KEY}`, onEnabledExtensionsChanged);
- global.settings.connect(`changed::${DISABLE_USER_EXTENSIONS_KEY}`, onEnabledExtensionsChanged);
- global.settings.connect(`changed::${EXTENSION_DISABLE_VERSION_CHECK_KEY}`, _onVersionValidationChanged);
-
- enabledExtensions = getEnabledExtensions();
-
- let finder = new ExtensionUtils.ExtensionFinder();
- finder.connect('extension-found', (finder, extension) => {
- loadExtension(extension);
- });
- finder.scanExtensions();
-}
-
-function enableAllExtensions() {
- if (enabled)
- return;
-
- if (!initted) {
- _loadExtensions();
- initted = true;
- } else {
- enabledExtensions.forEach(uuid => {
- enableExtension(uuid);
+
+ _onEnabledExtensionsChanged() {
+ let newEnabledExtensions = this._getEnabledExtensions();
+
+ if (!this._enabled)
+ return;
+
+ // Find and enable all the newly enabled extensions: UUIDs found in the
+ // new setting, but not in the old one.
+ newEnabledExtensions.filter(
+ uuid => !this._enabledExtensions.includes(uuid)
+ ).forEach(uuid => {
+ this.enableExtension(uuid);
});
+
+ // Find and disable all the newly disabled extensions: UUIDs found in the
+ // old setting, but not in the new one.
+ this._enabledExtensions.filter(
+ item => !newEnabledExtensions.includes(item)
+ ).forEach(uuid => {
+ this.disableExtension(uuid);
+ });
+
+ this._enabledExtensions = newEnabledExtensions;
+ }
+
+ _onVersionValidationChanged() {
+ // we want to reload all extensions, but only enable
+ // extensions when allowed by the sessionMode, so
+ // temporarily disable them all
+ this._enabledExtensions = [];
+ for (let uuid in ExtensionUtils.extensions)
+ this.reloadExtension(ExtensionUtils.extensions[uuid]);
+ this._enabledExtensions = this._getEnabledExtensions();
+
+ if (Main.sessionMode.allowExtensions) {
+ this._enabledExtensions.forEach(uuid => {
+ this.enableExtension(uuid);
+ });
+ }
}
- enabled = true;
-}
-function disableAllExtensions() {
- if (!enabled)
- return;
+ _loadExtensions() {
+ global.settings.connect(`changed::${ENABLED_EXTENSIONS_KEY}`,
+ this._onEnabledExtensionsChanged.bind(this));
+ global.settings.connect(`changed::${DISABLE_USER_EXTENSIONS_KEY}`,
+ this._onEnabledExtensionsChanged.bind(this));
+ global.settings.connect(`changed::${EXTENSION_DISABLE_VERSION_CHECK_KEY}`,
+ this._onVersionValidationChanged.bind(this));
+
+ this._enabledExtensions = this._getEnabledExtensions();
- if (initted) {
- extensionOrder.slice().reverse().forEach(uuid => {
- disableExtension(uuid);
+ let finder = new ExtensionUtils.ExtensionFinder();
+ finder.connect('extension-found', (finder, extension) => {
+ this.loadExtension(extension);
});
+ finder.scanExtensions();
+ }
+
+ enableAllExtensions() {
+ if (this._enabled)
+ return;
+
+ if (!this._initted) {
+ this._loadExtensions();
+ this._initted = true;
+ } else {
+ this._enabledExtensions.forEach(uuid => {
+ this.enableExtension(uuid);
+ });
+ }
+ this._enabled = true;
}
- enabled = false;
-}
-
-function _sessionUpdated() {
- // For now sessionMode.allowExtensions controls extensions from both the
- // 'enabled-extensions' preference and the sessionMode.enabledExtensions
- // property; it might make sense to make enabledExtensions independent
- // from allowExtensions in the future
- if (Main.sessionMode.allowExtensions) {
- if (initted)
- enabledExtensions = getEnabledExtensions();
- enableAllExtensions();
- } else {
- disableAllExtensions();
+ disableAllExtensions() {
+ if (!this._enabled)
+ return;
+
+ if (this._initted) {
+ this._extensionOrder.slice().reverse().forEach(uuid => {
+ this.disableExtension(uuid);
+ });
+ }
+
+ this._enabled = false;
}
-}
-function init() {
- Main.sessionMode.connect('updated', _sessionUpdated);
- _sessionUpdated();
-}
+ _sessionUpdated() {
+ // For now sessionMode.allowExtensions controls extensions from both the
+ // 'enabled-extensions' preference and the sessionMode.enabledExtensions
+ // property; it might make sense to make enabledExtensions independent
+ // from allowExtensions in the future
+ if (Main.sessionMode.allowExtensions) {
+ if (this._initted)
+ this._enabledExtensions = this._getEnabledExtensions();
+ this.enableAllExtensions();
+ } else {
+ this.disableAllExtensions();
+ }
+ }
+};
+Signals.addSignalMethods(ExtensionManager.prototype);